package com.cmw.socket.l7.client;

import com.cmw.socket.bean.ServerInfo;
import com.cmw.socket.utils.CloseUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * TCP 客户端
 * @author chengmingwei
 * @date 2020-06-27 18:20
 */
@Slf4j
public class TCPClient {

    private final Socket socket;

    private final ReadHandler readHandler;

    private final PrintStream printStream;

    public TCPClient(Socket socket, ReadHandler readHandler) throws IOException {
        this.socket = socket;
        this.readHandler = readHandler;
        this.printStream = new PrintStream(socket.getOutputStream());
    }

    public void exit(){
        readHandler.exit();
        CloseUtils.close(socket, printStream);
    }

    public void send(String msg){
        printStream.println(msg);
    }

    public  static TCPClient startWith(ServerInfo serverInfo) throws IOException {
        Socket socket = new Socket();
        //超时时间
        socket.setSoTimeout(3000);
        //连接本地，端口2000； 超时时间3000ms
        socket.connect(new InetSocketAddress(Inet4Address.getByName(serverInfo.getAddress()), serverInfo.getPort()),3000);
        log.info("已发起服务器连接，并进入后续流程...");
        log.info("客户端信息：IP -> {},\t Port -> {}", socket.getLocalAddress(), socket.getLocalPort());
        log.info("服务器信息：IP -> {},\t Port -> {}", socket.getInetAddress(), socket.getPort());
        try{
            ReadHandler readHandler = new ReadHandler(socket.getInputStream());
            readHandler.start();
            return new TCPClient(socket, readHandler);
        }catch (Exception e){
            log.error("连接异常，错误原因：{}", e.getMessage());
        }finally {
            CloseUtils.close(socket);
        }
        return null;
    }

    static class ReadHandler extends Thread{
        private boolean done = false;
        private final InputStream inputStream;

        public ReadHandler(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            super.run();
            try{
                //得到输入流，用于接收数据
                BufferedReader socketInput = new BufferedReader(new InputStreamReader(this.inputStream));
                do{
                    String str;
                    try {
                        str = socketInput.readLine();
                    } catch (IOException e) {
                        //e.printStackTrace();
                        continue;
                    }
                    if(null == str || str.equals("")){
                        log.error("连接已关闭，无法读取数据！");
                        break;
                    }
                    //打印到屏幕
                    log.info(str);
                }while (!done);
            }catch (Exception e){
                if(!done){
                    log.error("连接异常断开：{}", e.getMessage());
                }
            }finally {
                //连接关闭
                CloseUtils.close(inputStream);
            }
        }

        void exit(){
            done = true;
            CloseUtils.close(inputStream);
        }
    }
}
